﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using Dsl.Ped.Common.Commands;
using GalaSoft.MvvmLight.Command;

namespace Dsl.Ped.Framework.Projections.CollectionProjections.ExpandableCollection
{
    /// <summary>
    /// <see cref="ExpandableCollection"/> organizes items into a list that can
    /// be extended by clicking the plus button, as follows: 
    /// a + b + c + d + ...
    /// </summary>
    public class ExpandableCollectionProjection : ItemsControl
    {
        #region Fields

        /// <summary>
        /// <see cref="DependencyProperty"/> of commands that can be applied for extending the collection of new items
        /// </summary>
        public static DependencyProperty CommandsProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> of an action that is applied to remove an item from a collection
        /// </summary>
        public static DependencyProperty RemoveItemProperty;

        /// <summary>
        /// <see cref="FrameworkElement"/> collection representing all items
        /// </summary>
        private ObservableCollection<FrameworkElement> itemControls;

        /// <summary>
        /// Command that is executed when the remove button is clicked
        /// </summary>
        private RelayCommand<object> removeObjectCommand = null;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes static members of the <see cref="ExpandableCollectionProjection"/> class.
        /// </summary>
        static ExpandableCollectionProjection()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ExpandableCollectionProjection), new FrameworkPropertyMetadata(typeof(ExpandableCollectionProjection)));

            CommandsProperty = DependencyProperty.Register(
                "Commands", typeof(List<IMenuCommand>), typeof(ExpandableCollectionProjection),
                    new FrameworkPropertyMetadata(null));

            RemoveItemProperty = DependencyProperty.Register(
                "RemoveItem", typeof(Action<object>), typeof(ExpandableCollectionProjection),
                    new FrameworkPropertyMetadata(null));
        }

        #endregion

        #region Members

        /// <summary>
        /// Gets or sets <see cref="FrameworkElement"/> collection. It represents items in an expandable
        /// collection
        /// </summary>
        public ObservableCollection<FrameworkElement> ItemControls
        {
            get { return this.itemControls; }
            set { this.itemControls = value; }
        }

        /// <summary>
        /// Gets or sets commands that can be applied to extend the collection of new item
        /// </summary>
        public List<IMenuCommand> Commands
        {
            get { return (List<IMenuCommand>)this.GetValue(CommandsProperty); }
            set { SetValue(CommandsProperty, value); }
        }

        /// <summary>
        /// Gets or sets the <see cref="Action"/> to remove an item from the expandable
        /// collection
        /// </summary>
        public Action<object> RemoveItem
        {
            get { return (Action<object>)GetValue(RemoveItemProperty); }
            set { SetValue(RemoveItemProperty, value); }
        }

        /// <summary>
        /// Gets the command that invokes remove of an item from the collection
        /// </summary>
        public RelayCommand<object> RemoveObjectCommand
        {
            get
            {
                return this.removeObjectCommand ?? 
                    (this.removeObjectCommand = new RelayCommand<object>(this.OnRemoveObjectCommand));
            }
        } 

        #endregion

        #region Methods

        /// <summary>
        /// Handler method of a <see cref="RemoveObjectCommand"/>
        /// </summary>
        /// <param name="obj">Item to be removed</param>
        private void OnRemoveObjectCommand(object obj)
        {
            RemoveItem(obj);
        }

        #endregion
    }
}
